package com.microservice.microservicemovie.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 〈一句话功能简述〉
 * 〈功能详细描述〉
 *
 * @author bf
 * @create 2017/11/7
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */

@RestController
@RequestMapping
public class MovieController {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * HystrixCommand 计算断路器何事打开合适关闭，以及发生故障时应该做什么（回掉）
     *  例如：默认超时时间 2S ，超时后就走回调
     *  这种方式，回调方法的入参和出参必须一样
     *
     *  出现异常：FallbackDefinitionException: fallback method wasn't found: findUserById([class java.lang.Long])
     *   若 回调方法的返回值和入参和该方法上面不一致的话，那么就会出现这种错误
     *
     *  HystrixProperty 配置 一些断路器的基本状态
     *      例如：execution.isolation.thread.timeoutInMilliseconds 超时时间（默认2S）
     *      circuitBreaker.errorThresholdPercentage value = 50 errorThresholdPercentage 断路器错误请求百分比
     *  execution.isolation.strategy 设置执行的 隔离策略
     *      如果你设置了 @SessionScope 或者 @RequestScope 那么可能会出现 运行时异常，找不到范围的上下文，那时候才设置他
     *      隔离策略有两个模式：1.THREAD  每个服务单独分开定义限制的请求数； 2. SEMAPHORE  请求数号量计数（整体的一个量）
     *      可以理解为执行的线程，THREAD 重启线程执行，SEMAPHORE单个线程执行
     *
     *      @HystrixCommand(fallbackMethod = "findUserById", commandProperties = {
     * @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
     * }
     *
     *  ignoreExceptions: 忽略的异常，当访问的地方抛出配置的异常时，那么就不会执行后续的 fallback
     *      , ignoreExceptions = Exception.class
     * @param id
     * @return
     */
    @GetMapping(value = {"/movie/{id}"})
    public String findById(@PathVariable Long id){
        // throw new RuntimeException("哇哈哈哈哈");
        return restTemplate.getForObject("http://microservice-user/user/" + id, String.class);
    }

    /**
     * 还可以往下继续传递事件
     *
     *  方法 抛出 异常的时候，可使用 Throwable 对异常进行记录和拦截
     * @param id
     * @return
     * @throws Exception
     */
    @HystrixCommand(fallbackMethod = "findUserById2")
    public String findUserById(Long id, Throwable e) throws Exception{
        System.out.println("error: " + e.getMessage());

        // Thread.sleep(3000L);
        return "Hystrix ERROR user";
    }

    public String findUserById2(Long id){
        return "Error 22222";
    }

}
